package com.itheima.prize.api.action;

import com.itheima.prize.api.config.LuaScript;
import com.itheima.prize.commons.config.RabbitKeys;
import com.itheima.prize.commons.config.RedisKeys;
import com.itheima.prize.commons.db.entity.*;
import com.itheima.prize.commons.utils.ApiResult;
import com.itheima.prize.commons.utils.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/api/act")
@Api(tags = {"抽奖模块"})
public class ActController {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private LuaScript luaScript;

    @GetMapping("/limits/{gameid}")
    @ApiOperation(value = "剩余次数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "gameid", value = "活动id", example = "1", required = true)
    })
    public ApiResult<Object> limits(@PathVariable int gameid, HttpServletRequest request) {
        //获取活动基本信息
        CardGame game = (CardGame) redisUtil.get(RedisKeys.INFO + gameid);
        if (game == null) {
            return new ApiResult<>(-1, "活动未加载", null);
        }
        //获取当前用户
        HttpSession session = request.getSession();
        CardUser user = (CardUser) session.getAttribute("user");
        if (user == null) {
            return new ApiResult(-1, "未登陆", null);
        }
        //用户可抽奖次数
        Integer enter = (Integer) redisUtil.get(RedisKeys.USERENTER + gameid + "_" + user.getId());
        if (enter == null) {
            enter = 0;
        }
        //根据会员等级，获取本活动允许的最大抽奖次数
        Integer maxenter = (Integer) redisUtil.hget(RedisKeys.MAXENTER + gameid, user.getLevel() + "");
        //如果没设置，默认为0，即：不限制次数
        maxenter = maxenter == null ? 0 : maxenter;

        //用户已中奖次数
        Integer count = (Integer) redisUtil.get(RedisKeys.USERHIT + gameid + "_" + user.getId());
        if (count == null) {
            count = 0;
        }
        //根据会员等级，获取本活动允许的最大中奖数
        Integer maxcount = (Integer) redisUtil.hget(RedisKeys.MAXGOAL + gameid, user.getLevel() + "");
        //如果没设置，默认为0，即：不限制次数
        maxcount = maxcount == null ? 0 : maxcount;

        //幸运转盘类，先给用户随机剔除，再获取令牌，有就中，没有就说明抢光了
        //一般这种情况会设置足够的商品，卡在随机上
        Integer randomRate = (Integer) redisUtil.hget(RedisKeys.RANDOMRATE + gameid, user.getLevel() + "");
        if (randomRate == null) {
            randomRate = 100;
        }

        Map map = new HashMap();
        map.put("maxenter", maxenter);
        map.put("enter", enter);
        map.put("maxcount", maxcount);
        map.put("count", count);
        map.put("randomRate", randomRate);

        return new ApiResult<>(1, "成功", map);
    }


    @GetMapping("/go/{gameid}")
    @ApiOperation(value = "抽奖")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "gameid", value = "活动id", example = "1", required = true)
    })
    public ApiResult<CardProduct> act(@PathVariable int gameid, HttpServletRequest request) {
        //TODO：任务6.1-抽奖业务-抽奖接口
        CardGame game = (CardGame) redisUtil.get(RedisKeys.INFO + gameid);
        if (game == null) {
            CardUserGame userGame1 = new CardUserGame();
            userGame1.setGameid(6);
            userGame1.setUserid(6);
            return new ApiResult<CardProduct>(0, "未找到活动", null);

        }
        Date now = new Date();
        if (now.before(game.getStarttime())) {
            // 活动未开始
            return new ApiResult<>(-1, "活动未开始", null);
        }
        if (now.after(game.getEndtime())) {
            //活动已结束
            return new ApiResult<>(-1, "活动已结束", null);
        }
        CardUser user = (CardUser) request.getSession().getAttribute("user");
        if (user == null) {
            return new ApiResult<>(-1, "未登陆", null);
        }
        //是否参加过活动
        String flag = (String) redisUtil.get(RedisKeys.USERGAME + gameid + "_" + user.getId());
        if(flag == null){
            //用户参与次数+1
            //第一次参与活动，投递参与活动信息 存入redis标记用户参与过活动
            redisUtil.set(RedisKeys.USERGAME+gameid+"_"+user.getId(),"flag");
            CardUserGame userGame = new CardUserGame();
            userGame.setUserid(user.getId());
            userGame.setGameid(gameid);
            userGame.setCreatetime(now);
            log.error("投递参与信息" + userGame.toString());
            rabbitTemplate.convertAndSend(RabbitKeys.EXCHANGE_DIRECT, RabbitKeys.QUEUE_PLAY, userGame);

        }

        //最大中奖数
        Integer maxGoal = (Integer) redisUtil.hget(RedisKeys.MAXGOAL + gameid, user.getLevel() + "");

        luaScript.init();
        Long result = luaScript.tokenCheck(gameid, user.getId(), maxGoal);

        if (result == -1) {
            return new ApiResult(-1, "您的抽奖次数已用完", null);
        }
        if (result == -2) {
            return new ApiResult(-1, "奖品已抽光", null);
        }
        if (result == 0) {
            return new ApiResult(-1, "未中奖", null);
        }
        //1.中奖次数+1
        redisUtil.incr(RedisKeys.USERHIT + gameid + "_" + user.getId(), 1);

        //获取奖品信息
        CardProduct info = (CardProduct) redisUtil.get(RedisKeys.TOKEN + gameid + "_" + result);
        log.info("中奖了" + info.getName());

        //投递中奖信息
        CardUserHit userHit = new CardUserHit();
        userHit.setUserid(user.getId());
        userHit.setGameid(gameid);
        userHit.setProductid(info.getId());
        //中奖时间 = token/1000+startTime  中奖时间
        long hitTime = result / 1000 + (game.getStarttime().getTime());
        userHit.setHittime(new Date(hitTime));

        log.error("投递中奖信息" + userHit.toString());
        rabbitTemplate.convertAndSend(RabbitKeys.EXCHANGE_DIRECT, RabbitKeys.QUEUE_HIT, userHit);

        return new ApiResult<CardProduct>(1, "成功", info);


    }


    @GetMapping("/info/{gameid}")
    @ApiOperation(value = "缓存信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "gameid", value = "活动id", example = "1", required = true)
    })
    public ApiResult info(@PathVariable int gameid) {
        // TODO：任务5.2-抽奖业务-抽奖接口
        Map<String, Object> gameDataMap = new HashMap<>();

        // 1. 获取活动信息
        Object gameInfo = redisUtil.get(RedisKeys.INFO + gameid);
        if (gameInfo == null) {
            return new ApiResult(0, "没有数据", null);
        }
        gameDataMap.put("gameInfo", gameInfo);

        // 2. 获取规则（Hash）
        Map<Object, Object> maxEnter = redisUtil.hmget(RedisKeys.MAXENTER + gameid);
        Map<Object, Object> maxGoal = redisUtil.hmget(RedisKeys.MAXGOAL + gameid);
        Map<Object, Object> randomRate = redisUtil.hmget(RedisKeys.RANDOMRATE + gameid);
        gameDataMap.put("maxEnter", maxEnter);
        gameDataMap.put("maxGoal", maxGoal);
        gameDataMap.put("randomRate", randomRate);

        // 3. 获取 token 列表
        List<Object> tokenList = redisUtil.lrange(RedisKeys.TOKENS + gameid, 0, -1);
        gameDataMap.put("tokenList", tokenList);

        // 4. 获取每个 token 对应的奖品
        List<Object> tokenProductList = new ArrayList<>();
        if (tokenList != null) {
            for (Object token : tokenList) {
                String tokenKey = RedisKeys.TOKEN + gameid + "_" + token;
                Object product = redisUtil.get(tokenKey);
                tokenProductList.add(product);
            }
        }
        gameDataMap.put("tokenProductList", tokenProductList);

        // 5. 返回成功结果
        return new ApiResult(1, "成功", gameDataMap);
    }
}
